import tkinter as tk
from tkinter import ttk, messagebox
from datetime import datetime, timedelta
import pickle
import os
import sys
import ctypes

if sys.platform == 'win32':
    ctypes.windll.user32.ShowWindow(ctypes.windll.kernel32.GetConsoleWindow(), 0)  # 0=隐藏
elif sys.platform == 'darwin':
    sys.stdout = open('/dev/null', 'w')  # MacOS重定向输出

class EnhancedScheduler:
    def __init__(self, root):
        self.root = root
        self.root.title(" 招办排班系统ver1.0 - 2025年9月")
        self.current_date = datetime(2025, 9, 1)  # 基准日期
        self.time_slots = ["08:10-09:50", "10:20-12:00", "14:00-15:40", "16:10-17:50"]  # 每天4个时段

        # 初始化数据
        self.data_file = "存档.pkl"
        self.load_data()

        # 界面构建
        self.setup_ui()
        self.create_schedule_grid()

    def setup_ui(self):
        """构建主界面"""
        # 控制面板
        control_frame = ttk.Frame(self.root, padding="10")
        control_frame.pack(fill=tk.X)

        # 周次选择（1-20周）
        ttk.Label(control_frame, text="当前周次:").grid(row=0, column=0)
        self.week_var = tk.IntVar(value=1)
        ttk.Spinbox(control_frame, from_=1, to=20, textvariable=self.week_var,
                    width=5, command=self.refresh_schedule).grid(row=0, column=1, padx=5)


        # 功能按钮
        ttk.Button(control_frame, text="添加学生", command=self.add_student_dialog).grid(row=0, column=2, padx=5)
        ttk.Button(control_frame, text="管理有课时间", command=self.manage_unavailable).grid(row=0, column=3, padx=5)
        # 在控制面板添加删除按钮（与添加按钮并列）
        #ttk.Button(control_frame, text="删除学生", command=self.delete_student).grid(row=0, column=4, padx=5)
        # 在setup_ui()中修改删除按钮绑定：
        ttk.Button(
            control_frame,
            text="删除学生",
            style="Danger.TButton",
            command=self.show_delete_dialog  # 改为调用窗口方法
        ).grid(row=0, column=4, padx=5)

        # 排班表格框架
        self.schedule_frame = ttk.Frame(self.root, padding="10")
        self.schedule_frame.pack(fill=tk.BOTH, expand=True)

        # 状态栏
        self.status_var = tk.StringVar()
        self.update_status()
        ttk.Label(self.root, textvariable=self.status_var, relief=tk.SUNKEN).pack(fill=tk.X)

        # 样式配置
        self.setup_styles()

    def show_delete_dialog(self):
        """删除学生窗口"""
        delete_win = tk.Toplevel(self.root)
        delete_win.title(" 删除学生 ")
        delete_win.geometry("300x200")

        # 学生选择下拉框
        ttk.Label(delete_win, text="选择学生:").pack(pady=10)
        self.student_var = tk.StringVar()
        student_combo = ttk.Combobox(
            delete_win,
            textvariable=self.student_var,
            values=list(self.students.keys()),
            state="readonly"
        )
        student_combo.pack(pady=5)

        # 删除按钮
        ttk.Button(
            delete_win,
            text="确认删除",
            style="Danger.TButton",
            command=lambda: self.confirm_delete(delete_win)
        ).pack(pady=15)

        # 窗口居中
        delete_win.update_idletasks()
        x = (delete_win.winfo_screenwidth() - delete_win.winfo_width()) // 2
        y = (delete_win.winfo_screenheight() - delete_win.winfo_height()) // 2
        delete_win.geometry(f"+{x}+{y}")

    def confirm_delete(self, window):
        """带农历日期的二次确认"""
        student = self.student_var.get()
        if not student:
            messagebox.showwarning(" 警告", "请选择学生", parent=window)
            return

        if messagebox.askyesno(
                "确认删除",
                f"确定删除【{student}】？\n"
                f"⚠️ 所有相关排班记录将同时清除",
                parent=window
        ):
            self._execute_deletion(student)
            window.destroy()

    def _execute_deletion(self, name):
        """执行删除操作"""
        # 删除学生数据
        del self.students[name]

        # 清除关联排班
        self.assignments = {k: v for k, v in self.assignments.items() if v != name}

        self.save_data()
        self.refresh_schedule()
        messagebox.showinfo(" 完成", f"{name} 已从系统删除")

    '''
        def delete_student(self, student_name):
        """删除学生及其所有关联数据"""
        if student_name not in self.students:
            messagebox.showwarning(" 警告", f"{student_name}不存在", parent=self.root)
            return

        # 确认对话框
        confirm = messagebox.askyesno(
            "确认删除",
            f"确定删除学生【{student_name}】？\n（操作时间：{today} 19:36）",
            parent=self.root
        )
        if not confirm:
            return
            # 删除学生数据
        del self.students[student_name]

        # 删除相关排班记录
        self.assignments = {
            k: v for k, v in self.assignments.items()
            if v != student_name
        }

        self.save_data()
        self.refresh_schedule()
        messagebox.showinfo(" 成功", f"{student_name}已删除", parent=self.root)
    '''
    def setup_styles(self):
        """配置界面样式"""
        style = ttk.Style()
        style.configure("Available.TButton", foreground="green")
        style.configure("Assigned.TButton", foreground="black", background="#4E7CA1")
        style.configure("Header.TLabel", font=('Helvetica', 10, 'bold'))

    def create_schedule_grid(self):
        """创建排班表格"""
        for widget in self.schedule_frame.winfo_children():
            widget.destroy()

        # 表头（仅显示星期）
        week_days = ["周一", "周二", "周三", "周四", "周五"]
        for col, day in enumerate(week_days, 1):
            ttk.Label(
                self.schedule_frame,
                text=day,
                style="Header.TLabel",
                font=('Microsoft YaHei', 10, 'bold')  # 加粗显示
            ).grid(row=0, column=col, padx=5, pady=5)

        # 时间段行
        for row, slot in enumerate(self.time_slots, 1):
            ttk.Label(self.schedule_frame, text=slot).grid(row=row, column=0, padx=5, pady=5)

            # 排班单元格
            for col in range(1, 6):
                btn = ttk.Button(self.schedule_frame, text="", width=15,
                                 command=lambda r=row, c=col: self.handle_cell_click(r, c))
                btn.grid(row=row, column=col, padx=2, pady=2)
                setattr(self, f"cell_{row}_{col}", btn)

        self.refresh_schedule()

    def calculate_date(self, week, weekday):
        """计算具体日期"""
        days_map = {"周一": 0, "周二": 1, "周三": 2, "周四": 3, "周五": 4}
        return self.current_date + timedelta(weeks=week - 1, days=days_map[weekday])

    def update_status(self):
        """更新状态栏"""
        current_week = self.week_var.get()
        start_date = self.current_date + timedelta(weeks=current_week - 1)
        end_date = start_date + timedelta(days=4)
        current_time = datetime.now().strftime("%H:%M:%S")
        self.status_var.set(
            f"第{current_week}周 | {start_date.strftime('%m/%d')}-{end_date.strftime('%m/%d')}  | "
            f"总学生数: {len(self.students)}  | "
            f"当前时间: {current_time}"
        )

    def refresh_schedule(self):
        """刷新排班表显示"""
        current_week = self.week_var.get()
        week_days = ["周一", "周二", "周三", "周四", "周五"]
        self.update_status()

        for row in range(1, len(self.time_slots) + 1):
            for col in range(1, 6):
                cell = getattr(self, f"cell_{row}_{col}")
                cell.state(["!disabled"])
                cell.config(text="", style="TButton")

                # 获取当前单元格信息
                weekday = week_days[col - 1]
                time_key = (current_week, weekday, row)

                # 显示已排班信息
                if time_key in self.assignments:
                    cell.config(text=self.assignments[time_key], style="Assigned.TButton")
                    continue

                    # 显示可用学生数
                available = self.get_available_students(current_week, weekday, row)
                if available:
                    cell.config(text=f"{len(available)} 人可用", style="Available.TButton")

    def get_available_students(self, week, weekday, slot):
        """获取可用学生列表"""
        return [name for name, data in self.students.items()
                if not self.is_time_unavailable(data, week, weekday, slot)]

    def is_time_unavailable(self, student_data, week, weekday, slot):
        """检查时间段是否不可用"""
        # 检查常规不可用时间
        for unavail in student_data.get("unavailable", []):
            if unavail[0] == week and unavail[1] == weekday and unavail[2] == slot:
                return True
        return False

    def handle_cell_click(self, row, col):
        """处理单元格点击事件"""
        current_week = self.week_var.get()
        week_days = ["周一", "周二", "周三", "周四", "周五"]
        weekday = week_days[col - 1]

        # 获取可用学生
        available = self.get_available_students(current_week, weekday, row)
        if not available:
            self.status_var.set(f"{weekday}  第{row}节课无学生可用")
            return

            # 创建选择菜单
        menu = tk.Menu(self.root, tearoff=0)
        for student in available:
            menu.add_command(label=student,
                             command=lambda s=student: self.assign_student(s, row, col, current_week, weekday))

        # 显示菜单
        cell = getattr(self, f"cell_{row}_{col}")
        menu.tk_popup(cell.winfo_rootx(), cell.winfo_rooty() + cell.winfo_height())

    def assign_student(self, student, row, col, week, weekday):
        """分配学生到指定时间段"""
        # 保存分配记录
        if "assignments" not in self.__dict__:
            self.assignments = {}

        time_key = (week, weekday, row)
        self.assignments[time_key] = student
        self.save_data()

        # 更新界面
        cell = getattr(self, f"cell_{row}_{col}")
        cell.config(text=student, style="Assigned.TButton")
        self.status_var.set(f" 已安排 {student} 在第{week}周{weekday}第{row}节课")

    def add_student_dialog(self):
        """添加学生对话框"""
        win = tk.Toplevel(self.root)
        win.title(" 添加新学生")

        ttk.Label(win, text="学生姓名:").grid(row=0, column=0, padx=5, pady=5)
        name_entry = ttk.Entry(win)
        name_entry.grid(row=0, column=1, padx=5, pady=5)

        ttk.Button(win, text="确认添加",
                   command=lambda: self.add_student(name_entry.get(), win)).grid(row=1, columnspan=2, pady=5)

    def add_student(self, name, window):
        """添加学生到系统"""
        if not name:
            messagebox.showwarning(" 警告", "请输入学生姓名")
            return

        if name in self.students:
            messagebox.showwarning(" 警告", "该学生已存在")
            return

        self.students[name] = {"unavailable": []}
        self.save_data()
        window.destroy()
        self.refresh_schedule()

    def manage_unavailable(self):
        """管理不可用时间窗口"""
        if not self.students:
            messagebox.showinfo(" 提示", "请先添加学生")
            return

        win = tk.Toplevel(self.root)
        win.title(" 设置有课时间")

        # 学生选择
        ttk.Label(win, text="选择学生:").grid(row=0, column=0, padx=5, pady=5)
        student_var = tk.StringVar()
        student_dropdown = ttk.Combobox(win, textvariable=student_var,
                                        values=list(self.students.keys()))
        student_dropdown.grid(row=0, column=1, padx=5, pady=5)

        # 周次选择（多选）
        ttk.Label(win, text="选择周次:").grid(row=1, column=0, padx=5, pady=5)
        week_frame = ttk.Frame(win)
        week_frame.grid(row=1, column=1, padx=5, pady=5)

        self.week_vars = []
        for i in range(4):  # 4行5列
            for j in range(5):
                week = i * 5 + j + 1
                if week > 20:
                    break
                var = tk.BooleanVar()
                cb = ttk.Checkbutton(week_frame, text=f"第{week}周", variable=var)
                cb.grid(row=i, column=j, sticky="w")
                self.week_vars.append((week, var))

        # 星期选择
        ttk.Label(win, text="选择星期:").grid(row=2, column=0, padx=5, pady=5)
        weekday_var = tk.StringVar(value="周一")
        ttk.Combobox(win, textvariable=weekday_var,
                     values=["周一", "周二", "周三", "周四", "周五"]).grid(row=2, column=1, padx=5, pady=5)

        # 时间段选择
        ttk.Label(win, text="选择时间段:").grid(row=3, column=0, padx=5, pady=5)
        slot_var = tk.IntVar(value=1)
        ttk.Combobox(win, textvariable=slot_var,
                     values=list(range(1, len(self.time_slots) + 1))).grid(row=3, column=1, padx=5, pady=5)

        # 确认按钮
        ttk.Button(win, text="保存设置",
                   command=lambda: self.save_unavailable(
                       student_var.get(), weekday_var.get(), slot_var.get(), win)
                   ).grid(row=4, columnspan=2, pady=10)

    def save_unavailable(self, student, weekday, slot, window):
        """保存不可用时间设置"""
        if not student:
            messagebox.showwarning(" 警告", "请选择学生")
            return

        selected_weeks = [week for week, var in self.week_vars if var.get()]
        if not selected_weeks:
            messagebox.showwarning(" 警告", "请至少选择一个周次")
            return

        for week in selected_weeks:
            new_entry = (week, weekday, slot)
            if new_entry not in self.students[student]["unavailable"]:
                self.students[student]["unavailable"].append(new_entry)

        self.save_data()
        messagebox.showinfo(" 成功", f"已为{student}添加{len(selected_weeks)}条有课时间")
        window.destroy()
        self.refresh_schedule()

        # ...（数据加载保存方法load_data/save_data与之前相同）...

    def load_data(self):
        """加载保存的数据"""
        if os.path.exists(self.data_file):
            with open(self.data_file, "rb") as f:
                data = pickle.load(f)
                self.students = data.get("students", {})
                self.assignments = data.get("assignments", {})
        else:
            # 默认示例数据
            self.students = {
                "空空zZ": {"unavailable": [(1, "周一", 1), (1, "周三", 3)]},
                "ql": {"unavailable": [(1, "周二", 2), (2, "周五", 4)]},
                "szb": {"unavailable": [(3, "周四", 5)]}
            }
            self.assignments = {}

    def save_data(self):
        """保存数据到文件"""
        with open(self.data_file, "wb") as f:
            pickle.dump({
                "students": self.students,
                "assignments": self.assignments
            }, f)

if __name__ == "__main__":
    root = tk.Tk()
    app = EnhancedScheduler(root)
    root.mainloop()